/*
 *   Copyright (c) 2010-2022, SIUFUNG
 */
package net.siufung.market.base.dept.mapper;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import net.siufung.core.exception.BizServiceException;
import net.siufung.core.model.VerifyRepeatDto;
import net.siufung.core.model.enums.DeletedEnum;
import net.siufung.core.model.enums.MethodEventEnum;
import net.siufung.core.utils.StringPool;
import net.siufung.market.base.dept.controller.assembler.DeptAssembler;
import net.siufung.market.base.dept.controller.model.vo.DeptVo;
import net.siufung.market.base.dept.mapper.entity.Dept;
import net.siufung.mybatis.base.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统部门 Mapper 接口
 * </p>
 *
 * @author 陈建峰
 * @since 2022-07-13 22:40:52
 */
@Mapper
public interface IDeptMapper extends BaseMapper<Dept> {

    /**
     * 获取树
     * @param parentId 父级
     * @return List<Tree<String>>
     * */
    default List<Tree<String>> getTreeList(String parentId){
        return getTreeList(parentId, null);
    };

    /**
     * 获取树
     * @param parentId 父级
     * @param deptName 组织名称
     * @return List<Tree<String>>
     * */
    default List<Tree<String>> getTreeList(String parentId, String deptName) {
        List<DeptVo> deptVoList = Lists.newArrayList();
        List<Dept> deptList = Lists.newArrayList();
        List<Dept> allDeptList = this.selectList(
                new LambdaQueryWrapper<Dept>()
                        .eq(Dept::getDeleted, DeletedEnum.NOT.getValue())
                        .like(!Strings.isNullOrEmpty(deptName), Dept::getDeptName, deptName)
                        .orderByAsc(Dept::getCreatedAt));
        if(Strings.isNullOrEmpty(parentId)){
            parentId = StringPool.ZERO;
        }
        if(StringPool.ZERO.equals(parentId)){
            deptList = Lists.newCopyOnWriteArrayList(allDeptList);
        } else {
            this.getChildDeptList(deptList, parentId, allDeptList);
            deptList = deptList.stream().collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(() ->
                                    new TreeSet<>(Comparator.comparing(Dept::getId))), ArrayList::new)
            );
        }

        if(CollectionUtils.isEmpty(deptList)){
            parentId = StringPool.MINUS_ONE;
            DeptVo deptVo = new DeptVo();
            deptVo.setId(StringPool.ZERO);
            deptVo.setDeptName("无数据默认节点");
            deptVo.setParentId(parentId);
            deptVoList.add(deptVo);
        } else {
            List<String> parentIdList = deptList.stream().map(Dept::getParentId)
                    .distinct().collect(Collectors.toList());
            List<Dept> parentDeptList = allDeptList.stream()
                    .filter(element -> parentIdList.contains(element.getId())).collect(Collectors.toList());
            deptVoList = DeptAssembler.fromList(deptList, parentDeptList);
        }

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        return TreeUtil.build(deptVoList, parentId, treeNodeConfig, (treeNode, tree) -> {
            tree.setId(treeNode.getId());
            tree.setParentId(treeNode.getParentId());
            tree.setWeight(treeNode.getSequence());
            tree.setName(treeNode.getDeptName());
            tree.putExtra("deptCode", treeNode.getDeptCode());
            tree.putExtra("deptName", treeNode.getDeptName());
            tree.putExtra("deptType", treeNode.getDeptType());
            tree.putExtra("deptParentName", treeNode.getDeptParentName());
            tree.putExtra("deptFullName", treeNode.getDeptFullName());
            tree.putExtra("level", treeNode.getLevel());
            tree.putExtra("sequence", treeNode.getSequence());
            tree.putExtra("description", treeNode.getDescription());
        });
    }

    /**
     * 递归获得组织列表
     * @param deptList 部门递归集合
     * @param parentId 父级组织id
     */
    default void getChildDeptList(List<Dept> deptList, Serializable parentId){
        if(Objects.isNull(parentId)){
            throw new BizServiceException("组织parentId为空！");
        }
        Dept dept = this.selectById(parentId);
        if(!Objects.isNull(dept)){
            deptList.add(dept);
            List<Dept> childDeptList = this
                    .selectList(new LambdaQueryWrapper<Dept>()
                            .eq(Dept::getDeleted, DeletedEnum.NOT.getValue())
                            .eq(Dept::getParentId, parentId));
            if(!CollectionUtils.isEmpty(childDeptList)){
                for (Dept childDept : childDeptList) {
                    getChildDeptList(deptList, childDept.getId());
                }
            }
        }
    }

    /**
     * 递归获得组织列表
     * @param deptList 部门递归集合
     * @param parentId 父级组织id
     * @param allDeptList 所有父级组织
     */
    default void getChildDeptList(List<Dept> deptList, Serializable parentId, List<Dept> allDeptList){
        if(Objects.isNull(parentId)){
            throw new BizServiceException("组织parentId为空！");
        }
        Dept dept = this.selectById(parentId);
        if(!Objects.isNull(dept)){
            deptList.add(dept);
            List<Dept> childDeptList = allDeptList.stream()
                    .filter(element ->
                            DeletedEnum.NOT.equals(DeletedEnum.get(element.getDeleted()))
                                    && parentId.equals(element.getParentId()))
                    .collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(childDeptList)){
                for (Dept childDept : childDeptList) {
                    getChildDeptList(deptList, childDept.getId(), allDeptList);
                }
            }
        }
    }

    /**
     * 验证部门名称不能重复
     * @param verifyRepeatDto 重复
     * @return Boolean
     */
    default Boolean checkDeptNameNotRepeat(VerifyRepeatDto<String> verifyRepeatDto){
        if(verifyRepeatDto.getMethodEventEnum().equals(MethodEventEnum.ADD)){
            return 0 == this.selectCount(new LambdaQueryWrapper<Dept>()
                    .eq(Dept::getDeptName, verifyRepeatDto.getVerifyKeyValue()));
        } else if(verifyRepeatDto.getMethodEventEnum().equals(MethodEventEnum.UPDATE)){
            return 0 == this.selectCount(new LambdaQueryWrapper<Dept>()
                    .eq(Dept::getDeptName, verifyRepeatDto.getVerifyKeyValue())
                    .ne(Dept::getId, verifyRepeatDto.getPk()));
        }
        return Boolean.FALSE;
    }

    /**
     * 验证部门编码不能重复
     * @param verifyRepeatDto 重复
     * @return Boolean
     */
    default Boolean checkDeptCodeNotRepeat(VerifyRepeatDto<String> verifyRepeatDto){
        if(verifyRepeatDto.getMethodEventEnum().equals(MethodEventEnum.ADD)){
            return 0 == this.selectCount(new LambdaQueryWrapper<Dept>()
                    .eq(Dept::getDeptCode, verifyRepeatDto.getVerifyKeyValue()));
        } else if(verifyRepeatDto.getMethodEventEnum().equals(MethodEventEnum.UPDATE)){
            return 0 == this.selectCount(new LambdaQueryWrapper<Dept>()
                    .eq(Dept::getDeptCode, verifyRepeatDto.getVerifyKeyValue())
                    .ne(Dept::getId, verifyRepeatDto.getPk()));
        }
        return Boolean.FALSE;
    }
}
